load("@rules_cc//cc:defs.bzl", "cc_toolchain")
load(":ios_toolchain_config.bzl", "provide_ios_toolchain_config")
load(":linux_amd64_toolchain_config.bzl", "provide_linux_amd64_toolchain_config")
load(":mac_toolchain_config.bzl", "provide_mac_toolchain_config")
load(":ndk_linux_arm64_toolchain_config.bzl", "ndk_cc_toolchain_config")
load(":windows_toolchain_config.bzl", "provide_windows_amd64_toolchain_config")

package(
    default_applicable_licenses = ["//:license"],
)

licenses(["notice"])

# https://bazel.build/docs/toolchains
# https://bazel.build/reference/be/platform#toolchain
toolchain(
    name = "clang_linux_x64_toolchain",
    # Where should we run this toolchain?
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
        # We do not want an extra constraint here related to the hermetic toolchain because
        # we want the toolchain to run on any Linux x64 machine (and it certainly can).
    ],
    # What can this toolchain build?
    target_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
        # We want to be able to explicitly tell Bazel to use this toolchain, and not the
        # default one on a user's machine or on the RBE worker. Thus we need an extra constraint
        # that we can use to differentiate the "stock" C++ toolchain from our hermetic one and
        # force that use by specifying the target platform.
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":linux_amd64_host",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

# Our one mac toolchain can run on either Intel Macs or M1 Macs, however Bazel does not allow you to specify
# more than one cpu type in exec_compatible_with. Thus, we list the same toolchain twice.
toolchain(
    name = "clang_mac_x64_toolchain",
    exec_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:x86_64",
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":mac_host_and_target_match",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

toolchain(
    name = "clang_mac_arm64_toolchain",
    exec_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:arm64",
    ],
    target_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:arm64",
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":mac_host_and_target_match",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

# Cross compilation toolchain for an Intel Mac host and Apple silicon target
toolchain(
    name = "clang_host_mac_x64_target_mac_arm64_toolchain",
    exec_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:arm64",
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":mac_target_arm64",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

toolchain(
    name = "clang_host_mac_arm64_target_mac_x64_toolchain",
    exec_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:arm64",
    ],
    target_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:x86_64",
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":mac_target_x64",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

# Windows x64 toolchain.
toolchain(
    name = "clang_windows_x64_toolchain",
    exec_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
        "//bazel/platform:use_hermetic_toolchain",
    ],
    toolchain = ":windows_host",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

toolchain(
    name = "clang_ios_arm64_toolchain",
    exec_compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:arm64",
    ],
    target_compatible_with = [
        "@platforms//os:ios",
        "@platforms//cpu:arm64",
    ],
    toolchain = ":ios_target_arm64",
    # https://github.com/bazelbuild/rules_cc/blob/8bb0eb5c5ccd96b91753bb112096bb6993d16d13/cc/BUILD#L32-L36
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

# Based on:
# https://skia.googlesource.com/skcms/+/ba39d81f9797aa973bdf01aa6b0363b280352fba/toolchain/BUILD.bazel#28
toolchain(
    name = "linux_amd64_ndk_arm64_toolchain",
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:android",
        "@platforms//cpu:arm64",
    ],
    toolchain = ":linux_amd64_ndk_arm64",
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

# Based on:
# https://skia.googlesource.com/skcms/+/ba39d81f9797aa973bdf01aa6b0363b280352fba/toolchain/BUILD.bazel#42
toolchain(
    name = "linux_amd64_ndk_arm32_toolchain",
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:android",
        "@platforms//cpu:armv7",
    ],
    toolchain = ":linux_amd64_ndk_arm32",
    toolchain_type = "@rules_cc//cc:toolchain_type",
)

filegroup(name = "not_implemented")

filegroup(
    name = "archive_linux_amd64_files",
    srcs = [
        "linux_trampolines/ar_trampoline_linux.sh",
        "@clang_linux_amd64//:archive_files",
    ],
)

filegroup(
    name = "compile_linux_amd64_files",
    srcs = [
        "linux_trampolines/clang_trampoline_linux.sh",
        "@clang_linux_amd64//:compile_files",
    ],
)

filegroup(
    name = "link_linux_amd64_files",
    srcs = [
        # Bazel usually assumes it is talking to Clang when linking.
        "linux_trampolines/clang_trampoline_linux.sh",
        "@clang_linux_amd64//:link_files",
    ],
)

filegroup(
    name = "all_linux_amd64_files",
    srcs = [
        ":archive_linux_amd64_files",
        ":compile_linux_amd64_files",
        ":link_linux_amd64_files",
    ],
)

filegroup(
    name = "archive_mac_files",
    srcs = [
        "mac_trampolines/ar_trampoline_mac.sh",
        "@clang_mac//:archive_files",
    ],
)

filegroup(
    name = "compile_mac_files",
    srcs = [
        "mac_trampolines/clang_trampoline_mac.sh",
        "@clang_mac//:compile_files",
    ],
)

filegroup(
    name = "link_mac_files",
    srcs = [
        "mac_trampolines/clang_trampoline_mac.sh",
        "@clang_mac//:link_files",
    ],
)

filegroup(
    name = "all_mac_files",
    srcs = [
        ":archive_mac_files",
        ":compile_mac_files",
        ":link_mac_files",
    ],
)

filegroup(
    name = "archive_windows_files",
    srcs = [
        "windows_trampolines/ar_trampoline_windows.bat",
        "@clang_windows_amd64//:archive_files",
    ],
)

filegroup(
    name = "compile_windows_files",
    srcs = [
        "windows_trampolines/clang_trampoline_windows.bat",
        "@clang_windows_amd64//:compile_files",
    ],
)

filegroup(
    name = "link_windows_files",
    srcs = [
        # Bazel usually assumes it is talking to Clang when linking.
        "windows_trampolines/clang_trampoline_windows.bat",
        "@clang_windows_amd64//:link_files",
    ],
)

filegroup(
    name = "all_windows_files",
    srcs = [
        ":archive_windows_files",
        ":compile_windows_files",
        ":link_windows_files",
    ],
)

filegroup(
    name = "archive_ios_files",
    srcs = [
        "ios_trampolines/ar_trampoline_ios.sh",
        "@clang_ios//:archive_files",
    ],
)

filegroup(
    name = "compile_ios_files",
    srcs = [
        "ios_trampolines/clang_trampoline_ios.sh",
        "@clang_ios//:compile_files",
    ],
)

filegroup(
    name = "link_ios_files",
    srcs = [
        "ios_trampolines/clang_trampoline_ios.sh",
        "@clang_ios//:link_files",
    ],
)

filegroup(
    name = "all_ios_files",
    srcs = [
        ":compile_ios_files",
        ":link_ios_files",
    ],
)

provide_linux_amd64_toolchain_config(
    name = "linux_amd64_toolchain_config",
)

provide_mac_toolchain_config(
    name = "mac_host_toolchain_config",
)

provide_mac_toolchain_config(
    name = "mac_arm64_toolchain_config",
    cpu = "arm64",
)

provide_mac_toolchain_config(
    name = "mac_x64_toolchain_config",
    cpu = "x64",
)

provide_windows_amd64_toolchain_config(
    name = "windows_amd64_toolchain_config",
)

provide_ios_toolchain_config(
    name = "ios_arm64_toolchain_config",
    cpu = "arm64",
)

# https://bazel.build/reference/be/c-cpp#cc_toolchain
cc_toolchain(
    name = "linux_amd64_host",
    # Use by the rust toolchain when linking
    # https://github.com/bazelbuild/rules_rust/blob/dab425760656c449d3a0f73c490be92c240b6ef2/rust/private/rustc.bzl#L627
    all_files = ":all_linux_amd64_files",
    ar_files = ":archive_linux_amd64_files",
    compiler_files = ":compile_linux_amd64_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_linux_amd64_files",
    module_map = "@clang_linux_amd64//:generated_module_map",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":linux_amd64_toolchain_config",
)

cc_toolchain(
    name = "mac_host_and_target_match",
    all_files = ":all_mac_files",  # Apparently also used to compile objc code
    ar_files = ":archive_mac_files",
    compiler_files = ":compile_mac_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_mac_files",
    module_map = "@clang_mac//:generated_module_map",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":mac_host_toolchain_config",
)

cc_toolchain(
    name = "mac_target_arm64",
    all_files = ":all_mac_files",  # Apparently also used to compile objc code
    ar_files = ":archive_mac_files",
    compiler_files = ":compile_mac_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_mac_files",
    module_map = "@clang_mac//:generated_module_map",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":mac_arm64_toolchain_config",
)

cc_toolchain(
    name = "mac_target_x64",
    all_files = ":all_mac_files",  # Apparently also used to compile objc code
    ar_files = ":archive_mac_files",
    compiler_files = ":compile_mac_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_mac_files",
    module_map = "@clang_mac//:generated_module_map",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":mac_x64_toolchain_config",
)

cc_toolchain(
    name = "windows_host",
    all_files = ":all_windows_files",
    ar_files = ":archive_windows_files",
    compiler_files = ":compile_windows_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_windows_files",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = True,
    toolchain_config = ":windows_amd64_toolchain_config",
)

cc_toolchain(
    name = "ios_target_arm64",
    all_files = ":all_ios_files",  # Apparently also used to compile objc code
    ar_files = ":archive_ios_files",
    compiler_files = ":compile_ios_files",
    dwp_files = ":not_implemented",
    linker_files = ":link_ios_files",
    module_map = "@clang_ios//:generated_module_map",
    objcopy_files = ":not_implemented",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":ios_arm64_toolchain_config",
)

filegroup(
    name = "ndk_arm64_v8a_toolchain_all_files",
    srcs = [
        "android_trampolines/aarch64-linux-android-ar.sh",
        "android_trampolines/aarch64-linux-android-dwp.sh",
        "android_trampolines/aarch64-linux-android-ld.sh",
        "android_trampolines/aarch64-linux-android-nm.sh",
        "android_trampolines/aarch64-linux-android-objcopy.sh",
        "android_trampolines/aarch64-linux-android-objdump.sh",
        "android_trampolines/aarch64-linux-android-strip.sh",
        "android_trampolines/clang.sh",
    ] + ["@ndk_linux_amd64//:arm64_v8a_all_files"],
)

ndk_cc_toolchain_config(
    name = "ndk_arm64_v8a_toolchain_config",
    cpu = "arm64-v8a",
)

# Based on:
# https://skia.googlesource.com/skcms/+/ba39d81f9797aa973bdf01aa6b0363b280352fba/toolchain/BUILD.bazel#109
cc_toolchain(
    name = "linux_amd64_ndk_arm64",
    all_files = ":ndk_arm64_v8a_toolchain_all_files",
    ar_files = ":ndk_arm64_v8a_toolchain_all_files",
    compiler_files = ":ndk_arm64_v8a_toolchain_all_files",
    dwp_files = ":not_implemented",
    dynamic_runtime_lib = "@ndk_linux_amd64//:arm64_v8a_dynamic_runtime_libraries",
    linker_files = ":ndk_arm64_v8a_toolchain_all_files",
    objcopy_files = ":not_implemented",
    static_runtime_lib = "@ndk_linux_amd64//:arm64_v8a_static_runtime_libraries",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":ndk_arm64_v8a_toolchain_config",
)

filegroup(
    name = "ndk_armeabi_v7a_toolchain_all_files",
    srcs = [
        "android_trampolines/arm-linux-androideabi-ar.sh",
        "android_trampolines/arm-linux-androideabi-dwp.sh",
        "android_trampolines/arm-linux-androideabi-ld.sh",
        "android_trampolines/arm-linux-androideabi-nm.sh",
        "android_trampolines/arm-linux-androideabi-objcopy.sh",
        "android_trampolines/arm-linux-androideabi-objdump.sh",
        "android_trampolines/arm-linux-androideabi-strip.sh",
        "android_trampolines/clang.sh",
    ] + ["@ndk_linux_amd64//:armeabi_v7a_all_files"],
)

ndk_cc_toolchain_config(
    name = "ndk_armeabi_v7a_toolchain_config",
    cpu = "armeabi-v7a",
)

# Based on:
# https://skia.googlesource.com/skcms/+/ba39d81f9797aa973bdf01aa6b0363b280352fba/toolchain/BUILD.bazel#139
cc_toolchain(
    name = "linux_amd64_ndk_arm32",
    all_files = ":ndk_armeabi_v7a_toolchain_all_files",
    ar_files = ":ndk_armeabi_v7a_toolchain_all_files",
    compiler_files = ":ndk_armeabi_v7a_toolchain_all_files",
    dwp_files = ":not_implemented",
    dynamic_runtime_lib = "@ndk_linux_amd64//:armeabi_v7a_dynamic_runtime_libraries",
    linker_files = ":ndk_armeabi_v7a_toolchain_all_files",
    objcopy_files = ":not_implemented",
    static_runtime_lib = "@ndk_linux_amd64//:armeabi_v7a_static_runtime_libraries",
    strip_files = ":not_implemented",
    supports_param_files = False,
    toolchain_config = ":ndk_armeabi_v7a_toolchain_config",
)
